﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using IchiaTester.Modbus;
using Newtonsoft.Json;

namespace IchiaTester.Utils
{
    public class MessageBoxHandler
    {
        public static void ShowErrorMsg(string message, string error)
        {
            MessageBox.Show(message + "\n" + error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        public static void ShowInfoMsg(string message)
        {
            MessageBox.Show(message, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        public static void ShowWarnMsg(string message)
        {
            MessageBox.Show(message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    public class ListViewHandler
    {
    }

    public class KeyPressHandler
    {
        public static void Float_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsDigit(e.KeyChar) && (e.KeyChar != '.'))
            {
                e.Handled = true;
            }
            else if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1)
            {
                // 如果已經包含一個小數點，則不在允許輸入小數點
                e.Handled = true;
            }
        }

        public static void DigitControl_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsControl(e.KeyChar) || !char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        public static void DigitOnly_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        public static void StringOnly_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsDigit(e.KeyChar) || char.IsControl(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        public static void StringControl_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }
    }

    /// <summary>
    /// 数据计算器工具类
    /// </summary>
    public class DataCalculator
    {
        /// <summary>
        /// CRC校验
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool CRCCheck(byte[] data)
        {
            ushort crc = CalculateCRC(data, data.Length - 2);
            byte[] crcBytes = new byte[2];
            crcBytes[0] = (byte)(crc & 0x00FF);
            crcBytes[1] = (byte)(crc >> 8);
            if (crcBytes[0] == data[data.Length - 2] && crcBytes[1] == data[data.Length - 1])
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 计算CRC
        /// </summary>
        /// <param name="data">字节数组</param>
        /// <param name="length">长度</param>
        /// <returns></returns>
        private static ushort CalculateCRC(byte[] data, int length)
        {
            ushort crc = 0xFFFF;
            for (int pos = 0; pos < length; pos++)
            {
                crc ^= (ushort)data[pos];
                for (int i = 8; i != 0; i--)
                {
                    if ((crc & 0x0001) != 0)
                    {
                        crc >>= 1;
                        crc ^= 0xA001;
                    }
                    else
                    {
                        crc >>= 1;
                    }
                }
            }
            return crc;
        }
        
        /// <summary>
        /// 求double类型数组的平均数
        /// </summary>
        /// <param name="data">double类型数组</param>
        /// <returns></returns>
        public static double GetAverage(double[] data)
        {
            double sum = 0;
            foreach (double value in data)
            {
                sum += value;
            }
            return sum / data.Length;
        }
        
        /// <summary>
        /// 四分位距（interquartile range, IQR），又称四分差
        /// 求double类型数组的平均数
        /// </summary>
        /// <param name="data">double类型数组</param>
        /// <returns></returns>
        public static double GetAverageByIQR(double[] data)
        {
            // 对数据进行排序
            var sortedData = data.OrderBy(x => x).ToArray();

            // 计算第一四分位数（Q1）和第三四分位数（Q3）
            double Q1 = GetQuantile(sortedData, 0.25);
            double Q3 = GetQuantile(sortedData, 0.75);

            // 计算四分位距（IQR）
            double IQR = Q3 - Q1;

            // 定义倍数，例如1.5倍或3倍IQR
            double multiplier = 1.5;

            // 过滤掉异常值
            var filteredData = sortedData.Where(x => x >= Q1 - multiplier * IQR && x <= Q3 + multiplier * IQR).ToArray();

            // 计算过滤后数据的平均值
            return filteredData.Average();
        }

        /// <summary>
        /// Median 中位数
        /// 求double类型数组的平均数
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static double GetAverageByMedian(double[] data)
        {
            // 对数据进行排序
            var sortedData = data.OrderBy(x => x).ToArray();
            int n = sortedData.Length;
            if (n % 2 == 0)
            {
                // 如果数据个数为偶数，取中间两个数的平均值
                return (sortedData[n / 2 - 1] + sortedData[n / 2]) / 2.0;
            }
            else
            {
                // 如果数据个数为奇数，取中间的数
                return sortedData[n / 2];
            }
        }

        /// <summary>
        /// 分區間統計
        /// </summary>
        /// <param name="data"></param>
        /// <param name="lowerBound"></param>
        /// <param name="upperBound"></param>
        /// <returns></returns>
        public static bool GetValueByRange(double[] data, double lowerBound, double upperBound)
        {
            double NL = 0;
            double NH = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (data[i] < lowerBound)
                {
                    NL++;
                }
                else if (data[i] > upperBound)
                {
                    NH++;
                }
            }
            NL = NL / data.Length;
            NH = NH / data.Length;
            if (NL <= 0.01 && NH <= 0.01)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 利用標準差方法
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static double GetAverageByDeviation(double[] data)
        {
            double mean = data.Average();
            double sum = 0;
            foreach (double value in data)
            {
                sum += Math.Pow(value - mean, 2);
            }

            double variance = sum / data.Length;
            double stdDev = Math.Sqrt(variance);
            double lowerBound = mean - 3 * stdDev;
            double upperBound = mean + 3 * stdDev;
            double[] filteredData = data.Where(x => x >= lowerBound && x <= upperBound).ToArray();
            return filteredData.Average();
        }

        /// <summary>
        /// 利用分位方法
        /// </summary>
        /// <param name="sortedData"></param>
        /// <param name="percentile"></param>
        /// <returns></returns>
        private static double GetQuantile(double[] sortedData, double percentile)
        {
            int n = sortedData.Length;
            double index = (percentile * (n - 1));
            int lowerIndex = (int)Math.Floor(index);
            int upperIndex = (int)Math.Ceiling(index);
            double weight = index % 1;

            if (lowerIndex == upperIndex)
            {
                return sortedData[lowerIndex];
            }
            else
            {
                return (1 - weight) * sortedData[lowerIndex] + weight * sortedData[upperIndex];
            }
        }
    }

    /// <summary>
    /// 数据安全帮助类
    /// </summary>
    public class DataSecureHelper
    {
        /// <summary>
        /// 将输入的字符串hash加密后返回
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string GetHash(string input)
        {
            using (SHA256 hash = SHA256.Create())
            {
                byte[] bytes = hash.ComputeHash(Encoding.UTF8.GetBytes(input));
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    builder.Append(bytes[i].ToString("x2"));
                }
                return builder.ToString();
            }
        }
    }

    /// <summary>
    /// 串口处理器
    /// </summary>
    public class SerialPortHandler
    {
        /// <summary>
        /// 寻找可用的端口
        /// </summary>
        /// <returns>可用端口集合</returns>
        public static List<string> GetAvailableComPorts()
        {
            List<string> availablePorts = new List<string>();

            // 使用 SerialPort.GetPortNames() 方法獲取可用的 COM Port 名稱
            string[] portNames = SerialPort.GetPortNames();

            // 將可用的 COM Port 名稱添加到列表中
            foreach (string portName in portNames)
            {
                availablePorts.Add(portName);
            }
            return availablePorts;
        }

        /// <summary>
        /// 检查port是否存在
        /// </summary>
        /// <param name="targetPort"></param>
        /// <returns></returns>
        public static bool PortIsExist(string targetPort)
        {
            //Get all available serial ports
            string[] ports = SerialPort.GetPortNames();

            //檢查指定serial port是否存在
            bool portExists = Array.Exists(ports, port => port.Equals(targetPort, StringComparison.OrdinalIgnoreCase));

            if (portExists)
            {
                Console.WriteLine($"端口 {targetPort} 存在。");
                return true;
            }
            else
            {
                Console.WriteLine($"端口 {targetPort} 不存在。");
                return false;
            }
        }
    }

    /// <summary>
    /// ComboBox处理器
    /// </summary>
    public class ComboBoxHandler
    {
        /// <summary>
        /// 显示选中的串口号
        /// </summary>
        /// <param name="comboBox"></param>
        /// <param name="value"></param>
        public static void ConvertToSelectedIndex(ComboBox comboBox, string value)
        {
            for (int i = 0; i < comboBox.Items.Count; i++)
            {
                if (comboBox.Items[i].ToString() == value)
                {
                    comboBox.SelectedIndex = i;
                    break;
                }
                comboBox.SelectedIndex = -1;
            }
        }
    }

    /// <summary>
    /// TextBox处理器
    /// </summary>
    public class TextBoxHandler
    {
        //設置提示文字
        public void SetupHintText(TextBox textBox, string hintText, string defaultText)
        {
            if (string.IsNullOrEmpty(textBox.Text) || textBox.Text == defaultText)
            {
                textBox.Text = hintText;
                textBox.ForeColor = Color.Gray;
            }
            else
            {
                textBox.ForeColor = Color.Black;
            }
        }

        //清除提示文字
        public void ClearHintText(TextBox textBox, string hintText, string defaultText)
        {
            if (textBox.Text == hintText || textBox.Text == defaultText)
            {
                textBox.Text = "";
                textBox.ForeColor = Color.Black;
            }
        }
    }

    /// <summary>
    /// 校验和 计算器
    /// </summary>
    public class ChecksumCalculator
    {
        private ModbusRtu modbusRtu;

        //計算checksum
        public byte[] CalculateChecksum(byte[] data, int length, SerialPort serialPort)
        {
            modbusRtu = new ModbusRtu(serialPort);
            ushort checksum = 0;
            byte[] crc = new byte[2];
            checksum = modbusRtu.CalculateCRC(data, length);
            //注意:CRC位置尚未轉換
            crc[0] = (byte)(checksum >> 8);
            crc[1] = (byte)(checksum & 0x00FF);
            return crc;
        }
    }

    /// <summary>
    /// 数据检查处理器
    /// </summary>
    public class DataChecker
    {
        /// <summary>
        /// 检查输入的数据是否是Numeric类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool CheckIfNumeric(string input)
        {
            float floatResult;
            int intResult;

            if (float.TryParse(input, out floatResult))
            {
                Console.WriteLine($"{input} 是有效的浮點數: {floatResult}");
                return true;
            }
            else if (int.TryParse(input, out intResult))
            {
                Console.WriteLine($"{input} 是有效的整數: {intResult}");
                return true;
            }
            else
            {
                Console.WriteLine($"{input} 不是有效的數字");
                return false;
            }
        }

        public static bool CheckIfDontCare(string input)
        {
            if (input == "N/A")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    /// <summary>
    /// string 字符串拆分器
    /// </summary>
    public class StringSpliter
    {
        public static string[] SplitString(string input)
        {
            var result = input.Select(c => c.ToString()).ToArray();
            return result;
        }
    }

    /// <summary>
    /// 文件处理器
    /// </summary>
    public class FileHandler
    {
        /// <summary>
        /// 检查文件目录是否存在
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        public static bool CheckDirectory(string path)
        {
            if (!Directory.Exists(path))
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 获取文件名
        /// </summary>
        /// <param name="filter">设置文件过滤器，允许用户选择特定类型的文件</param>
        /// <param name="title"></param>
        /// <returns></returns>
        public static string GetFileName(string filter, string title)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = filter;
            // 设置 SaveFileDialog 对话框的标题
            saveFileDialog.Title = title;
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                return saveFileDialog.FileName;
            }
            return null;
        }

        /// <summary>
        /// 字符串转化为json
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="data"></param>
        /// <typeparam name="T"></typeparam>
        public static void SaveToJson<T>(string filePath, T data)
        {
            try
            {
                string json = JsonConvert.SerializeObject(data, Formatting.Indented);
                File.WriteAllText(filePath, json);
                Console.WriteLine("Data saved successfully!");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to save file: " + ex.Message);
            }
        }

        /// <summary>
        /// json转化为字符串
        /// </summary>
        /// <param name="filePath"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T LoadFromJson<T>(string filePath)
        {
            string json = File.ReadAllText(filePath);
            T data = JsonConvert.DeserializeObject<T>(json);
            Console.WriteLine("Data loaded successfully!");
            return data;
        }
    }
}